Skip to content

Do not set completed if NoSuchVersion in removeObjects#1710

Open
balamurugana wants to merge 1 commit into
minio:masterfrom
balamurugana:Do-not-set-completed-if-NoSuchVersion-in-removeObjects
Open

Do not set completed if NoSuchVersion in removeObjects#1710
balamurugana wants to merge 1 commit into
minio:masterfrom
balamurugana:Do-not-set-completed-if-NoSuchVersion-in-removeObjects

Conversation

@balamurugana

@balamurugana balamurugana commented Jun 24, 2026

Copy link
Copy Markdown
Member

Previously if batch object removal gets NoSuchVersion error only, the iterator stops processing next batches. This is fixed by continue processing next batches for NoSuchVersion but stops for other errors.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed object deletion to continue processing when delete responses only include ignored errors, preventing the operation from stopping too early.
    • Improved handling of partial delete failures so valid deletions can proceed as expected.

Previously if batch object removal gets `NoSuchVersion` error only,
the iterator stops processing next batches. This is fixed by continue
processing next batches for `NoSuchVersion` but stops for other
errors.

Signed-off-by: Bala.FA <bala@minio.io>
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

In MinioAsyncClient.removeObjects(...), the lazy iterator's populate() method now sets completed = error != null instead of unconditionally completed = true after calling setError(). This means iterations stop only when setError() actually records an error, not when all delete errors were filtered out as "NoSuchVersion".

Changes

removeObjects Iterator Completion Fix

Layer / File(s) Summary
Iterator early-exit condition
api/src/main/java/io/minio/MinioAsyncClient.java
Replaces completed = true with completed = error != null in the populate() post-error block so that NoSuchVersion-only responses do not prematurely mark the iterator as done.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🐇 A single line changed, a small fix indeed,
No NoSuchVersion shall stop our delete spree!
The iterator hops on without missing a beat,
error != null keeps the logic complete.
One line, one fix — the rabbit approves! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: removeObjects should not mark the iterator completed when only NoSuchVersion errors are returned.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/src/main/java/io/minio/MinioAsyncClient.java (1)

1120-1139: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Avoid recursive hasNext() now that NoSuchVersion-only batches continue.

With completed = error != null, many consecutive all-NoSuchVersion batches now flow into return hasNext(); (Line 1139), which can recurse per batch and eventually overflow the stack on large inputs. Switch this tail-recursive path to a loop.

💡 Proposed fix
           `@Override`
           public boolean hasNext() {
-            while (error == null && errorIterator == null && !completed) {
-              populate();
-            }
-
-            if (error == null && errorIterator != null) setError();
-            if (error != null) return true;
-            if (completed) return false;
-
-            errorIterator = null;
-            return hasNext();
+            while (true) {
+              while (error == null && errorIterator == null && !completed) {
+                populate();
+              }
+
+              if (error == null && errorIterator != null) setError();
+              if (error != null) return true;
+              if (completed) return false;
+
+              errorIterator = null;
+            }
           }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/src/main/java/io/minio/MinioAsyncClient.java` around lines 1120 - 1139,
The hasNext() implementation in MinioAsyncClient now recurses through repeated
all-NoSuchVersion batches via the final return hasNext() path, which can grow
the call stack on large inputs. Replace that tail-recursive fallback in
hasNext() with an explicit loop that keeps advancing until error, completion, or
a non-empty errorIterator is found, while preserving the current populate() and
setError() behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@api/src/main/java/io/minio/MinioAsyncClient.java`:
- Around line 1120-1139: The hasNext() implementation in MinioAsyncClient now
recurses through repeated all-NoSuchVersion batches via the final return
hasNext() path, which can grow the call stack on large inputs. Replace that
tail-recursive fallback in hasNext() with an explicit loop that keeps advancing
until error, completion, or a non-empty errorIterator is found, while preserving
the current populate() and setError() behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d16160ca-243f-478b-9bde-6b2fa6fa4aa6

📥 Commits

Reviewing files that changed from the base of the PR and between 942e2e5 and 80bce42.

📒 Files selected for processing (1)
  • api/src/main/java/io/minio/MinioAsyncClient.java

@shtripat shtripat left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants